package blazingbubble.network.game.strategy;

import blazingbubble.config.Config;
import blazingbubble.game.Bubble;
import blazingbubble.game.Field;
import blazingbubble.game.Game;
import blazingbubble.game.command.net.NetGameCommandFactory;
import blazingbubble.game.loader.LevelParser;
import moltencore.game.CannonData;
import moltencore.game.Grid;
import moltencore.game.collision.HorizontalLine;
import moltencore.game.collision.ICollidable;
import moltencore.game.collision.VerticalLine;
import moltencore.game.loader.Level;
import moltencore.game.loader.LevelLoader;
import moltencore.network.protocol.FieldLayout;
import moltencore.network.protocol.GridBubbleData;
import org.apache.log4j.Logger;
import spark.exception.LoadingException;
import spark.network.protocol.Response;
import spark.network.strategy.IProtocolHandleStrategy;
import spark.network.protocol.Acknowledgement;
import spark.network.protocol.Base;
import spark.utility.OutWrapper;

import java.util.ArrayList;
import java.util.Collection;

public class FieldLayoutStrategy implements IProtocolHandleStrategy<FieldLayout> {
	private Logger logger = Logger.getLogger(FieldLayoutStrategy.class);

	private Game game;
	private NetGameCommandFactory netGameCommandFactory;

	public FieldLayoutStrategy(Game game, NetGameCommandFactory netGameCommandFactory) {
		this.game = game;
		this.netGameCommandFactory = netGameCommandFactory;
	}

	@Override
	public void handle(FieldLayout packet, OutWrapper<Response> acknowledgement, Collection<Base> additionalData) {
		Field field = getField(packet);
		Grid grid = new Grid();
		for(GridBubbleData gridBubbleData : packet.getGridBubblesData()) {
			moltencore.game.bubble.Bubble positionHelper = new moltencore.game.bubble.Bubble(null, (short) 0);
			grid.snapToGrid(positionHelper, gridBubbleData.getGridPositionX(), gridBubbleData.getGridPositionY());
			Bubble bubble = new Bubble(gridBubbleData.getType(), gridBubbleData.getBubbleId());
			bubble.getPosition().copy(positionHelper.getPosition());
			bubble.setState(Bubble.State.Fixed);
			field.spawnBubble(bubble);
		}
		game.addField(field);
		if(game.getState() == Game.State.AllPlayersPairedWithFields) {
			netGameCommandFactory.getReadyToPlay().readyToPlay();
		}
		acknowledgement.value = new Acknowledgement(packet);
	}

	private Field getField(FieldLayout packet) {
		Level level = null;
		try {
			level = LevelLoader.loadLevel(Config.getLevelsPath() + "/" + packet.getFieldFile(), new LevelParser());
		}
		catch(LoadingException e) {
			throw new RuntimeException(e);
		}
		ArrayList<ICollidable> collidables = new ArrayList<ICollidable>();
		for(HorizontalLine horizontalLine : level.getHorizontalLines()) {
			collidables.add(new HorizontalLine(horizontalLine.getYPosition(), horizontalLine.isSticky()));
		}
		for(VerticalLine verticalLine : level.getVerticalLines()) {
			collidables.add(new VerticalLine(verticalLine.getXPosition(), verticalLine.isSticky()));
		}
		ArrayList<ICollidable> criticalAreas = new ArrayList<ICollidable>();
		for(HorizontalLine horizontalLine : level.getCriticalAreas()) {
			criticalAreas.add(new HorizontalLine(horizontalLine.getYPosition(), false));
		}
		ArrayList<ICollidable> killAreas = new ArrayList<ICollidable>();
		for(HorizontalLine horizontalLine : level.getKillAreas()) {
			killAreas.add(new HorizontalLine(horizontalLine.getYPosition(), false));
		}
		Field field = new Field(
				packet.getFieldId(), packet.getFieldFile(),
				false, false, collidables, criticalAreas, killAreas,
				level.getCannonData(), level.getResultPosition(),
				level.getNickPosition(), level.getScorePosition(),
				level.getLevelSprites());
		return field;
	}
}